<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/1/24 0024
 * Time: 17:36
 */
class Ws
{
    CONST HOST = '192.168.3.221';
    CONST POST = 8811;
    CONST CHART_POST = 8812;

    public $ws = null;
    public function __construct()
    {
        $this->ws = new swoole_websocket_server(self::HOST, self::POST);
        $this->ws->listen(self::HOST, self::CHART_POST, SWOOLE_SOCK_TCP);

        //设置静态文件的访问路径
        $this->ws->set([
            'worker_num' => 4,
            'task_worker_num' => 4,
            'enable_static_handler' => true,
            'document_root' => '/data/wwwroot/www/swoole-demo/mooc/tp5/public/static',
        ]);
        $this->ws->on('start', [$this, 'onStart']);
        $this->ws->on('workerstart', [$this, 'onWorkerStart']);
        $this->ws->on('request', [$this, 'onRequest']);
        $this->ws->on('open', [$this, 'onOpen']);
        $this->ws->on('message', [$this, 'onMessage']);
        $this->ws->on('task', [$this, 'onTask']);
        $this->ws->on('finish', [$this, 'onFinish']);
        $this->ws->on('close', [$this, 'onClose']);

        $this->ws->start();
    }


    public function onStart($server)
    {
        //主进程别名
        swoole_set_process_name('live_master');
    }


    /**
     * workerstart 回调
     * @param $server
     * @param $worker_id
     */
    public function onWorkerStart($server, $worker_id)
    {
        //加载tp框架的内容
//        define('APP_PATH', __DIR__ . '/../application/');
//        define('APP_EXTEND', __DIR__ . '/../extend');
//        require __DIR__ . '/../thinkphp/base.php';
//        think\Container::get('app')->run()->send();
        require __DIR__ . '/../public/index.php';
    }


    /**
     * request 回调
     * @param $request
     * @param $response
     */
    public function onRequest($request, $response)
    {
        //print_r($request->server);
        //不访问这个favicon.ico文件
        if($request->server['request_uri'] == '/favicon.ico'){
            $response->status(404);
            $response->end();
            return '';
        }

        $response->header("Content-Type", "text/html;charset=utf-8");
        $response->header("Access-Control-Allow-Origin", "*");
        $_GET = [];
        $_POST = [];
        $_FILES = [];
        if(isset($request->get)){
            foreach ($request->get as $k => $v){
                $_GET[$k] = $v;
            }
        }
        if(isset($request->post)){
            foreach ($request->post as $k => $v){
                $_POST[$k] = $v;
            }
        }
        if(isset($request->files)){
            foreach ($request->files as $k => $v){
                $_FILES[$k] = $v;
            }
        }
        if(isset($request->server)){
            $_SERVER = [];
            foreach ($request->server as $k => $v){
                $_SERVER[strtoupper($k)] = $v;
            }
        }

        $this->writeLog();

        //赋值，在其他地方使用
        $_POST['http_server'] = $this->ws;

        ob_start();
        // 执行应用并响应
        try{
            //run() 方法在thinkphp/library/think/app.php
            think\Container::get('app')->run()->send();
        }catch(\Exception $e){
            //todo
        }
        $res = ob_get_contents();
        ob_end_clean();
        $response->end($res);
    }



    /**
     * 监听ws连接事件
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request)
    {
        //print_r($ws);
        // fd 存入redis 有序集合 [1,2,3]
        \app\common\lib\redis\Predis::getInstance()->sAdd(config('redis.live_game_key'), $request->fd);
        echo "connect-client" .$request->fd.PHP_EOL;
    }

    /**
     * 监听ws消息事件
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame)
    {
        echo "server-push-message:{$frame->data}\n";
//        $ws->push($frame->fd, "server-push:" .date('Y-m-d H:i:s'));
    }


    /**
     * 任务
     * @param $serv swoole_server对象
     * @param $task_id  任务id
     * @param $worker_id worker进程id
     * @param $data 任务的内容
     */
    public function onTask($serv, $task_id, $worker_id, $data)
    {
        //分发 task 任务机制，让不同的任务走不同的逻辑
        $obj = new \app\common\lib\task\Task();
        //分发任务
        $method = $data['method'];
        $flag = $obj->$method($data['data'],$serv);

        return $flag;   //告诉worker，调finish
    }

    /**
     * 结束任务
     * @param $serv
     * @param $task_id  任务id
     * @param $data 任务处理的结果内容,ontask方法return的内容
     */
    public function onFinish($serv, $task_id, $data)
    {
        echo "takdId: {$task_id}\n";
        echo "finish-data-success:{$data}\n";
//        $serv->push($data, '5s后的数据');
    }

    /**
     * 监听ws关闭事件
     * @param $ws
     * @param $fd
     */
    public function onClose($http, $fd)
    {
        //fd 从redis的有序集合中删除
        \app\common\lib\redis\Predis::getInstance()->sRem(config('redis.live_game_key'), $fd);
        echo "close-clientid:{$fd}\n";
    }

    /**
     * 记录访问日志
     */
    public function writeLog()
    {
        $data = array_merge(['date' => date('y-m-d H:i:s')],$_GET,$_POST,$_SERVER);

        $logs = '';
        foreach($data as $key => $value){
            $logs .= $key . ":" . $value ." ";
        }
//        echo $logs.PHP_EOL.PHP_EOL;
        //异步写入文件
        swoole_async_writefile(APP_PATH.'../runtime/log/'.date('Ym').'/'.date('d')."_access.log", $logs.PHP_EOL, function($filename){
            //echo $filename;
        }, FILE_APPEND);
    }
}

new Ws();


// 监测8811端口是否一直在运行
// netstat anp | grep 8811  定时任务crontab  swoole->定时器

//信号源  sigterm  sigusr1  usr2   平滑重启
